import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_fancy_tree_view/flutter_fancy_tree_view.dart';

// Create a class to hold your hierarchical data (optional, could be a Map or
// any other data structure that's capable of representing hierarchical data).
class MyNode {
  const MyNode({
    required this.title,
    this.children = const <MyNode>[],
  });

  final String title;
  final List<MyNode> children;
}

class TreePage extends StatefulWidget {
  const TreePage({super.key});

  @override
  State<TreePage> createState() => _TreePageState();
}

class _TreePageState extends State<TreePage> {
  // 在本例中，使用了静态嵌套树，但使用了分层数据
  // 可以以多种不同的方式组合和存储。
  static const List<MyNode> roots = <MyNode>[
    MyNode(
      title: '腾讯公司',
      children: <MyNode>[
        MyNode(
          title: '企业发展事业群',
          children: <MyNode>[
            MyNode(title: '马化腾'),
            MyNode(title: '林二狗'),
            MyNode(title: '张小龙'),
          ],
        ),
        MyNode(title: '云与智慧产业事业群', children: <MyNode>[
          MyNode(title: '腾讯云'),
          MyNode(title: '腾讯音乐'),
          MyNode(title: '腾讯视频'),
        ]),
        MyNode(title: '平台与生态事业群',children: <MyNode>[
          MyNode(title: '微信'),
          MyNode(title: 'QQ'),
          MyNode(title: '微视'),
        ]),
        MyNode(title: '微信事业群',children: <MyNode>[
          MyNode(title: '微信支付'),
          MyNode(title: '微信读书'),
          MyNode(title: '微信小程序'),
        ]),
      ],
    ),
    MyNode(
      title: '阿里巴巴公司',
      children: <MyNode>[
        MyNode(
          title: '阿里巴巴集团',
          children: <MyNode>[
            MyNode(title: '马云'),
            MyNode(title: '张勇'),
            MyNode(title: '蔡崇信'),
          ],
        ),
        MyNode(title: '阿里巴巴云计算', children: <MyNode>[
          MyNode(title: '阿里云'),
          MyNode(title: '阿里巴巴云'),
          MyNode(title: '阿里巴巴云计算'),
        ]),
        MyNode(title: '阿里巴巴电商',children: <MyNode>[
          MyNode(title: '淘宝'),
          MyNode(title: '天猫'),
          MyNode(title: '菜鸟网络'),
        ]),
        MyNode(title: '阿里巴巴金融',children: <MyNode>[
          MyNode(title: '蚂蚁金服'),
          MyNode(title: '网商银行'),
          MyNode(title: '支付宝'),
        ]),
      ],
    ),
  ];

  // 这个控制器负责提供层次数据
  // 来创建树视图，还可以操作树节点的状态。
  late final TreeController<MyNode> treeController;

  @override
  void initState() {
    super.initState();
    treeController = TreeController<MyNode>(
      // 提供将用作起始点的根节点
      //遍历层次数据。
      roots: roots,
      // 为控制器提供一个回调，以获取类的子类
      //遍历分层数据时给定节点。避免做某事
      //在此方法中进行大量计算，它应该表现得像getter。
      childrenProvider: (MyNode node) => node.children,
    );
  }

  @override
  void dispose() {
    // 记得处置树控制器以释放资源。
    treeController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 这个包提供了一些不同的树视图来定制如何
    //你的分层数据被合并到你的应用中。在这个例子中，
    //如果你想使用一个没有自定义行为的TreeView
    //当父节点展开时，在树节点内和树节点外动画
    //和折叠，可以使用AnimatedTreeView代替。
    //树形视图小部件也有一个银色的变体，使它更容易
    //在复杂的滚动中合并层次数据
    //经验。
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tree View Example'),
      ),
      body: AnimatedTreeView<MyNode>(
        //树视图使用该控制器来构建平面表示
        //一个树形结构，这样它可以被SliverList延迟渲染。
        //它还用于存储和操作对象的不同状态
        //树节点。
        treeController: treeController,
        // 提供一个小部件构建器回调，将树节点映射到小部件。
        nodeBuilder: (BuildContext context, TreeEntry<MyNode> entry) {
          // 提供一个小部件在树视图中显示树节点。
          //
          // 可以是任何小部件，只要确保包含一个[TreeIndentation]
          //在其小部件子树中适当缩进树节点。
          return MyTreeTile(
            // 在你的贴图上添加一个键来避免同步后代动画。
            key: ValueKey(entry.node),
            // 在遍历时，树节点被封装在TreeEntry实例中
            //在树中，这些对象保存了节点的重要细节
            //相对于树，如:扩展状态，级别，父级等。
            // treeentry的寿命很短，每次都是TreeController。重建是
            //调用，为每个节点创建一个新的TreeEntry，因此它的属性
            //总是最新的。
            entry: entry,
            // Add a callback to toggle the expansion state of this node.
            onTap: () => treeController.toggleExpansion(entry.node),
          );
        },
      ),
    );
  }
}

// 创建一个小部件来显示树节点持有的数据。
class MyTreeTile extends StatelessWidget {
  const MyTreeTile({
    super.key,
    required this.entry,
    required this.onTap,
  });

  final TreeEntry<MyNode> entry;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      // 将您的内容包装在TreeIndentation小部件中，这将正确地
      //缩进节点(如果需要，绘制参考线)。
      //
      //如果你不想显示缩进指南，你可以替换它
      //带有Padding小部件的TreeIndentation，提供Padding值
      // EdgeInsetsDirectional。(开始:TreeEntry。level * indentAmount)
      child: TreeIndentation(
        entry: entry,
        // 如果需要，提供缩进引导。缩进导线可用于
        //为树节点的缩进添加装饰。
        //这也可以通过DefaultTreeIndentGuide来提供
        //继承放置在树视图之上的小部件。
        guide: const IndentGuide.connectingLines(indent: 48),
        // 要在缩进旁边呈现的小部件。TreeIndentation
        //尊重' directionalitymaybeof (context) '的文本方向
        //默认从左到右。
        child: Padding(
          padding: const EdgeInsets.fromLTRB(4, 8, 8, 8),
          child: Row(
            children: [
              // Add a widget to indicate the expansion state of this node.
              // See also: ExpandIcon.
              FolderButton(
                icon: Icon(Icons.person),
                closedIcon: Icon(Icons.expand_circle_down),
                openedIcon: Icon(Icons.arrow_circle_up),
                isOpen: entry.hasChildren ? entry.isExpanded : null,
                onPressed: entry.hasChildren ? onTap : null,
              ),
              Text(entry.node.title),
            ],
          ),
        ),
      ),
    );
  }
}
